package xyz.ssf.cloud.project.system.service.impl;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xyz.ssf.cloud.common.core.domain.PageResult;
import xyz.ssf.cloud.common.utils.SecurityUtils;
import xyz.ssf.cloud.project.system.domain.SysRole;
import xyz.ssf.cloud.project.system.domain.UserRole;
import xyz.ssf.cloud.project.system.domain.dto.RoleDTO;
import xyz.ssf.cloud.project.system.domain.dto.RoleQuery;
import xyz.ssf.cloud.project.system.domain.vo.RoleVO;
import xyz.ssf.cloud.project.system.domain.vo.UserRoleVO;
import xyz.ssf.cloud.project.system.mapper.SysRoleMapper;
import xyz.ssf.cloud.project.system.mapper.SysRoleMenuMapper;
import xyz.ssf.cloud.project.system.mapper.SysUserRoleMapper;
import xyz.ssf.cloud.project.system.service.SysRoleService;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 角色业务层处理
 */
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl implements SysRoleService {
    
    private final SysRoleMapper roleMapper;
    
    private final SysRoleMenuMapper roleMenuMapper;
    
    private final SysUserRoleMapper userRoleMapper;
    
    /**
     * 根据条件分页查询角色列表
     *
     * @param query 查询条件
     * @return 分页结果
     */
    @Override
    public PageResult<RoleVO> selectRoleList(RoleQuery query) {
        // 查询角色列表
        List<SysRole> roleList = roleMapper.selectRoleList(query);
        
        // 分页信息和数据转换
        PageResult<RoleVO> pageResult = new PageResult<>();
        pageResult.setCurrent(query.getPageNo());
        pageResult.setSize(query.getPageSize());
        
        // 转换为VO对象
        List<RoleVO> roleVOList = roleList.stream().map(role -> {
            RoleVO roleVO = new RoleVO();
            BeanUtils.copyProperties(role, roleVO);
            return roleVO;
        }).collect(Collectors.toList());
        
        pageResult.setRecords(roleVOList);
        
        // 获取总记录数
        int total = roleMapper.countRoleList(query);
        pageResult.setTotal(total);
        
        return pageResult;
    }
    
    /**
     * 根据用户ID查询角色列表
     *
     * @param userId 用户ID
     * @return 角色列表
     */
    @Override
    public List<SysRole> selectRolesByUserId(Long userId) {
        return roleMapper.selectRolesByUserId(userId);
    }
    
    /**
     * 查询所有角色
     *
     * @return 角色列表
     */
    @Override
    public List<SysRole> selectRoleAll() {
        return roleMapper.selectRoleAll();
    }
    
    /**
     * 根据用户ID获取角色选择框列表
     *
     * @param userId 用户ID
     * @return 选中角色ID列表
     */
    @Override
    public UserRoleVO getUserRoleList(Long userId) {
        UserRoleVO userRoleVO = new UserRoleVO();
        
        System.out.println("获取用户角色列表, userId: " + userId);
        
        // 查询所有正常状态的角色
        RoleQuery query = new RoleQuery();
        query.setRoleStatus("0");
        List<SysRole> roles = roleMapper.selectRoleList(query);
        
        System.out.println("查询到的角色数量: " + (roles != null ? roles.size() : 0));
        
        // 转换为VO
        List<RoleVO> roleVOList = roles.stream().map(role -> {
            RoleVO roleVO = new RoleVO();
            BeanUtils.copyProperties(role, roleVO);
            return roleVO;
        }).collect(Collectors.toList());
        
        userRoleVO.setRoles(roleVOList);
        
        // 查询用户已分配的角色ID
        try {
            List<SysRole> userRoles = roleMapper.selectRolesByUserId(userId);
            System.out.println("查询到的用户角色数量: " + (userRoles != null ? userRoles.size() : 0));
            
            List<Long> userRoleIds = userRoles.stream().map(SysRole::getId).collect(Collectors.toList());
            userRoleVO.setCheckedRoleIds(userRoleIds);
        } catch (Exception e) {
            System.err.println("查询用户角色异常: " + e.getMessage());
            e.printStackTrace();
            userRoleVO.setCheckedRoleIds(new ArrayList<>());
        }
        
        return userRoleVO;
    }
    
    /**
     * 通过角色ID查询角色
     *
     * @param roleId 角色ID
     * @return 角色对象信息
     */
    @Override
    public SysRole selectRoleById(Long roleId) {
        return roleMapper.selectRoleById(roleId);
    }
    
    /**
     * 校验角色名称是否唯一
     *
     * @param role 角色信息
     * @return 结果
     */
    @Override
    public boolean checkRoleNameUnique(SysRole role) {
        Long roleId = role.getId() == null ? -1L : role.getId();
        SysRole info = roleMapper.selectRoleByName(role.getRoleName());
        if (info != null && !info.getId().equals(roleId)) {
            return false;
        }
        return true;
    }
    
    /**
     * 校验角色编号是否唯一
     *
     * @param role 角色信息
     * @return 结果
     */
    @Override
    public boolean checkRoleCodeUnique(SysRole role) {
        Long roleId = role.getId() == null ? -1L : role.getId();
        SysRole info = roleMapper.selectRoleByCode(role.getRoleCode());
        if (info != null && !info.getId().equals(roleId)) {
            return false;
        }
        return true;
    }
    
    /**
     * 新增角色信息
     *
     * @param role 角色信息
     * @return 结果
     */
    @Override
    @Transactional
    public int insertRole(SysRole role) {
        // 设置创建者
        role.setCreateBy(SecurityUtils.getUsername());
        
        // 新增角色信息
        int rows = roleMapper.insertRole(role);
        
        // 如果有菜单权限，则保存角色菜单关联关系
        if (isNotEmpty(role.getMenuIds())) {
            insertRoleMenu(role);
        }
        
        return rows;
    }
    
    /**
     * 修改角色信息
     *
     * @param role 角色信息
     * @return 结果
     */
    @Override
    @Transactional
    public int updateRole(SysRole role) {
        // 设置更新者
        role.setUpdateBy(SecurityUtils.getUsername());
        
        // 修改角色信息
        int rows = roleMapper.updateRole(role);
        
        // 删除原有菜单权限
        roleMenuMapper.deleteRoleMenuByRoleId(role.getId());
        
        // 如果有菜单权限，则保存角色菜单关联关系
        if (isNotEmpty(role.getMenuIds())) {
            insertRoleMenu(role);
        }
        
        return rows;
    }
    
    /**
     * 修改角色状态
     *
     * @param role 角色信息
     * @return 结果
     */
    @Override
    public int updateRoleStatus(SysRole role) {
        // 设置更新者
        role.setUpdateBy(SecurityUtils.getUsername());
        return roleMapper.updateRoleStatus(role);
    }
    
    /**
     * 批量删除角色信息
     *
     * @param roleIds 需要删除的角色ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteRoleByIds(Long[] roleIds) {
        // 检查是否有用户在使用该角色
        for (Long roleId : roleIds) {
            SysRole role = selectRoleById(roleId);
            if (role == null) {
                throw new RuntimeException("角色不存在");
            }
            if (role.isAdmin()) {
                throw new RuntimeException("不允许删除超级管理员角色");
            }
            if (roleMapper.countUserRoleByRoleId(roleId) > 0) {
                throw new RuntimeException(String.format("%s已分配给用户，不能删除", role.getRoleName()));
            }
        }
        
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenu(roleIds);
        
        // 删除角色与用户关联
        userRoleMapper.deleteUserRoleByRoleIds(roleIds);
        
        // 删除角色
        return roleMapper.deleteRoleByIds(roleIds);
    }
    
    /**
     * 删除角色信息
     *
     * @param roleId 角色ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteRoleById(Long roleId) {
        // 检查是否有用户在使用该角色
        SysRole role = selectRoleById(roleId);
        if (role == null) {
            throw new RuntimeException("角色不存在");
        }
        if (role.isAdmin()) {
            throw new RuntimeException("不允许删除超级管理员角色");
        }
        if (roleMapper.countUserRoleByRoleId(roleId) > 0) {
            throw new RuntimeException(String.format("%s已分配给用户，不能删除", role.getRoleName()));
        }
        
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenuByRoleId(roleId);
        
        // 删除角色与用户关联
        userRoleMapper.deleteUserRoleByRoleId(roleId);
        
        // 删除角色
        return roleMapper.deleteRoleById(roleId);
    }
    
    /**
     * 查询角色关联的菜单ID集合
     *
     * @param roleId 角色ID
     * @return 菜单ID集合
     */
    @Override
    public List<Long> getRoleMenuList(Long roleId) {
        return roleMenuMapper.selectMenuIdsByRoleId(roleId);
    }
    
    /**
     * 保存角色和菜单关联关系
     *
     * @param roleId 角色ID
     * @param menuIds 菜单ID集合
     * @return 结果
     */
    @Override
    @Transactional
    public int saveRoleMenu(Long roleId, List<Long> menuIds) {
        // 删除原有角色菜单关联关系
        roleMenuMapper.deleteRoleMenuByRoleId(roleId);
        
        if (isNotEmpty(menuIds)) {
            // 构建批量插入的数据
            List<Object> list = new ArrayList<>();
            for (Long menuId : menuIds) {
                if (menuId == null) {
                    continue;
                }
                
                // 创建角色菜单对象
                UserRole rm = new UserRole();
                rm.setRoleId(roleId);
                rm.setUserId(menuId); // 此处使用UserRole复用，将menuId放在userId字段上
                list.add(rm);
            }
            
            if (list.size() > 0) {
                // 批量插入角色菜单关联关系
                return roleMenuMapper.batchRoleMenu(list);
            }
        }
        
        return 0;
    }
    
    /**
     * 为当前登录用户分配角色
     *
     * @param params 参数列表，第一个元素是用户ID，其余是角色ID
     * @return 结果
     */
    @Override
    @Transactional
    public int assignUserRole(List<Long> params) {
        if (params == null || params.size() < 1) {
            System.err.println("分配角色参数为空");
            return 0;
        }
        
        // 第一个元素是用户ID，其余是角色ID
        Long userId = params.get(0);
        if (userId == null) {
            System.err.println("用户ID为空");
            return 0;
        }
        
        System.out.println("分配角色，用户ID: " + userId);
        
        try {
            // 删除用户原有角色
            int deleteCount = userRoleMapper.deleteUserRoleByUserId(userId);
            System.out.println("删除用户原有角色数量: " + deleteCount);
            
            // 如果只有用户ID没有角色ID，直接返回成功
            if (params.size() <= 1) {
                System.out.println("没有需要分配的角色");
                return 1;
            }
            
            // 获取角色ID列表(除了第一个用户ID)并去重
            Set<Long> uniqueRoleIds = new HashSet<>();
            for (int i = 1; i < params.size(); i++) {
                Long roleId = params.get(i);
                if (roleId != null) {
                    uniqueRoleIds.add(roleId);
                }
            }
            
            System.out.println("需要分配的角色数量: " + uniqueRoleIds.size());
            
            if (!uniqueRoleIds.isEmpty()) {
                // 构建批量插入的数据
                List<Object> list = new ArrayList<>();
                for (Long roleId : uniqueRoleIds) {
                    // 创建用户角色对象
                    UserRole ur = new UserRole();
                    ur.setUserId(userId);
                    ur.setRoleId(roleId);
                    list.add(ur);
                    System.out.println("添加角色分配: 用户ID=" + userId + ", 角色ID=" + roleId);
                }
                
                if (!list.isEmpty()) {
                    try {
                        // 批量插入用户角色关联关系
                        int insertCount = userRoleMapper.batchUserRole(list);
                        System.out.println("插入角色分配数量: " + insertCount);
                        return insertCount;
                    } catch (Exception e) {
                        System.err.println("插入角色分配异常: " + e.getMessage());
                        e.printStackTrace();
                        throw e;
                    }
                }
            }
            
            return 1; // 没有角色也算成功
        } catch (Exception e) {
            System.err.println("分配角色异常: " + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }
    
    /**
     * 新增角色菜单信息
     *
     * @param role 角色对象
     */
    private void insertRoleMenu(SysRole role) {
        List<Object> list = new ArrayList<>();
        // 遍历菜单ID集合
        for (Long menuId : role.getMenuIds()) {
            // 创建角色菜单对象
            UserRole rm = new UserRole();
            rm.setRoleId(role.getId());
            rm.setUserId(menuId); // 此处使用UserRole复用，将menuId放在userId字段上
            list.add(rm);
        }
        
        if (list.size() > 0) {
            // 批量插入角色菜单关联关系
            roleMenuMapper.batchRoleMenu(list);
        }
    }
    
    /**
     * 判断集合是否为空
     * 
     * @param collection 集合
     * @return true-不为空，false-为空
     */
    private boolean isNotEmpty(Iterable<?> collection) {
        return collection != null && collection.iterator().hasNext();
    }
} 